package edu.gatech.cc.liam.core.rl.models;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;


public class JointActionIterator implements Iterator<Action[]>, Iterable<Action[]> {

	private Action[] lastJointActionReturned;
	private Iterator<? extends Action>[] currentActionIterators;
	private int[] currentActionNums;
	private ArrayList<? extends Iterable<? extends Action>> theActions;
	int numPlayers;
	
	public JointActionIterator(ArrayList<? extends Iterable<? extends Action>> theActions) {
		super();
		initIterators(theActions);
	}

	protected JointActionIterator() {
		super();
	}
	protected void initIterators(
			ArrayList<? extends Iterable<? extends Action>> theActions) {
		this.theActions = theActions;
		this.numPlayers = theActions.size();
		currentActionIterators = new Iterator[numPlayers];
		for(int i=0; i<numPlayers; i++) {
			currentActionIterators[i] = theActions.get(i).iterator();
		}
		lastJointActionReturned = new Action[numPlayers];
		for(int i=1; i<numPlayers; i++) {
			lastJointActionReturned[i] = currentActionIterators[i].next();
		}
		currentActionNums = new int[numPlayers];
		Arrays.fill(currentActionNums, 0);
		//the first action doesn't get set until the first call to next()
		currentActionNums[0] = -1;
	}
 
	@Override
	public boolean hasNext() {
		for(int i=0; i<numPlayers; i++){
			if(this.currentActionIterators[i].hasNext()){
				return true;
			}
		}
		return false;
	}

	@Override
	public Action[] next() {
		for(int i=0; i<numPlayers; i++) {
			if(currentActionIterators[i].hasNext()) {
				lastJointActionReturned[i] = currentActionIterators[i].next();
				currentActionNums[i]++;
				break;
			} else {
				currentActionIterators[i] = theActions.get(i).iterator();
				lastJointActionReturned[i] = currentActionIterators[i].next();
				currentActionNums[i]=0;
			}
		}
		return lastJointActionReturned.clone();
	}
	
	public int[] getCurrentActionNums() {
		return this.currentActionNums;
	}

	@Override
	public void remove() {
		throw new UnsupportedOperationException();			
	}

	@Override
	public Iterator<Action[]> iterator() {
		return this;
	}
	
	static ArrayList<Action> makeArrayListFromArray(Action[] theArray) {
		ArrayList<Action> returnArrayList = new ArrayList<Action>();
		for(int i=0; i<theArray.length; i++) {
			returnArrayList.add(theArray[i]);
		}
		return returnArrayList;
	}
	
	public static void main(String[] args) {
		ArrayList<Action> anActionList1 = new ArrayList<Action>();
		anActionList1.add(new NumberedAction(1));
		anActionList1.add(new NumberedAction(10));
		anActionList1.add(new NumberedAction(100));
		ArrayList<Action> anActionList2 = new ArrayList<Action>();
		anActionList2.add(new NumberedAction(2));
		anActionList2.add(new NumberedAction(20));
		ArrayList<Action> anActionList3 = new ArrayList<Action>();
		anActionList3.add(new NumberedAction(31));
		anActionList3.add(new NumberedAction(32));
		
		ArrayList<ArrayList<Action>> theActions = new ArrayList<ArrayList<Action>>();
		theActions.add(anActionList1);
		theActions.add(anActionList2);
			theActions.add(anActionList3);
		
		for(Action[] anIter : new JointActionIterator(theActions)) {
			System.out.println(Arrays.asList(anIter));
		}
	}
}
